package com.hymjweb.demo.framework.util;

import com.alibaba.fastjson.JSON;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.util.PublicSuffixMatcher;
import org.apache.http.conn.util.PublicSuffixMatcherLoader;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.Query;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Set;

public class HttpClientUtil {

	private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

	private RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(600000).setConnectTimeout(600000)
			.setConnectionRequestTimeout(600000).build();

	private static HttpClientUtil instance = null;

	private HttpClientUtil() {
	}

	public static HttpClientUtil getInstance() {
		if (instance == null) {
			instance = new HttpClientUtil();
		}
		return instance;
	}

	/**
	 * 发送 post请求
	 * 
	 * @param httpUrl
	 *            地址
	 * @param params
	 *            参数 格式:(urlencoded数据:key1=value1&key2=value2)
	 *            (json数据:{"aa":"bb","cc":"cc"}) 详见:
	 *            http://blog.csdn.net/tycoon1988/article/details/40080691
	 * @param contentType
	 *            参数如:"application/x-www-form-urlencoded","application/json","multipart/form-data","text/xml"
	 */
	public String sendHttpPost(String httpUrl, String params, String contentType) {
		HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
		try {
			// 设置参数
			StringEntity stringEntity = new StringEntity(params, "UTF-8");
			stringEntity.setContentType(contentType);
			httpPost.setEntity(stringEntity);
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
		return sendHttpPost(httpPost);
	}

	public String sendHttpPost(String httpUrl, Map<String, Object> paramsMap, String contentType) {
		String params = JSON.toJSONString(paramsMap);
		return sendHttpPost(httpUrl, params, contentType);
	}

    /**
     * 发送post请求，json数据格式
     * @author zhangyong created on 2019/9/18 6:16 PM
     * @param url 请求路径
     * @param params 请求参数集合
     * @return 返回值
     */
	public String post(String url, Map<String, Object> params) {
		return sendHttpPost(url, params, "application/json");
	}
	

	public String post(String url, String params) {
		return sendHttpPost(url, params, "application/json");
	}


	/**
	 * 根据url访问对应grid的action对应的方法.
	 * 
	 * @param url
	 *            发送的url
	 * @param params
	 *            元素 列如: pageIndex=0&pageSize=1231&sortField=1231&sortOrder=desc
	 * @param isSendOutPost
	 *            是否是对外发送.true 对外,false 对系统内部
	 * @return
	 * @throws Exception
	 * @author 余伟
	 * @serialData 2018年3月14日
	 */

	public String sendFormHttpPost(String url, String params, boolean isSendOutPost) throws Exception {
		if (isSendOutPost) {
			String address = getLocalIpAddressAndTomcatPort();
			url = address + url;
		}
		HttpPost httpPost = new HttpPost(url);
		if (!isSendOutPost) {
			ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
			HttpServletRequest request = sra.getRequest();
			String sessionId = request.getSession().getId();
			httpPost.setHeader("Cookie", "JSESSIONID=" + sessionId);//注意：下载表格时，要注意与tomcat》web.xml中cookie-config中保持一致
		}
		httpPost.addHeader(HTTP.CONTENT_TYPE, "application/x-www-form-urlencoded");
		StringEntity stringEntity = new StringEntity(params, "UTF-8");
		httpPost.setEntity(stringEntity);
		return sendHttpPost(httpPost);
	}

	/**
	 * 发送Post请求
	 * 
	 * @param httpPost
	 * @return
	 */
	public String sendHttpPost(HttpPost httpPost) {
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		HttpEntity entity = null;
		String responseContent = null;
		try {
			// 创建默认的httpClient实例.
			httpClient = HttpClients.createDefault();
			httpPost.setConfig(requestConfig);
			// 执行请求
			response = httpClient.execute(httpPost);
			entity = response.getEntity();
			responseContent = EntityUtils.toString(entity, "UTF-8");
		} catch (Exception e) {
			logger.error(e.getMessage());
		} finally {
			try {
				// 关闭连接,释放资源
				if (response != null) {
					response.close();
				}
				if (httpClient != null) {
					httpClient.close();
				}
			} catch (IOException e) {
				logger.error(e.getMessage());
			}
		}
		return responseContent;
	}

	/**
	 * 发送 get请求
	 * 
	 * @param httpUrl
	 */
	public String sendHttpGet(CloseableHttpClient httpClient1, String httpUrl) {// 测试暂时把String改成Object
		HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求
		return sendHttpGet(httpClient1, httpGet);
	}

	/**
	 * 发送 get请求Https
	 * 
	 * @param httpUrl
	 */
	public String sendHttpsGet(String httpUrl) {
		HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求
		return sendHttpsGet(httpGet);
	}

	/**
	 * 发送Get请求
	 * 
	 * @param httpGet
	 * @return
	 */
	private String sendHttpGet(CloseableHttpClient httpClient1, HttpGet httpGet) {// 测试暂时把String改成Object
		CloseableHttpClient httpClient = httpClient1;
		boolean isInnerCreate = false;

		CloseableHttpResponse response = null;
		HttpEntity entity = null;
		String responseContent = null;
		try {
			// 创建默认的httpClient实例.
			if (httpClient == null) {
				httpClient = HttpClients.createDefault();
				isInnerCreate = true;
			}
			httpGet.setConfig(requestConfig);

			// 执行请求
			response = httpClient.execute(httpGet);
			entity = response.getEntity();
			responseContent = EntityUtils.toString(entity, "UTF-8");
		} catch (Exception e) {
			logger.error(e.getMessage());
		} finally {
			try {
				// 关闭连接,释放资源
				if (response != null) {
					response.close();
				}
				if (isInnerCreate) {
					if (httpClient != null) {
						httpClient.close();
					}
				}
			} catch (IOException e) {
				logger.error(e.getMessage());
			}
		}
		return responseContent;
	}

	/**
	 * 发送Get请求Https
	 * 
	 * @param httpGet
	 * @return
	 */
	private String sendHttpsGet(HttpGet httpGet) {
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		HttpEntity entity = null;
		String responseContent = null;
		try {
			// 创建默认的httpClient实例.
			PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader
					.load(new URL(httpGet.getURI().toString()));
			DefaultHostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(publicSuffixMatcher);
			httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).build();
			httpGet.setConfig(requestConfig);
			// 执行请求
			response = httpClient.execute(httpGet);
			entity = response.getEntity();
			responseContent = EntityUtils.toString(entity, "UTF-8");
		} catch (Exception e) {
			logger.error(e.getMessage());
		} finally {
			try {
				// 关闭连接,释放资源
				if (response != null) {
					response.close();
				}
				if (httpClient != null) {
					httpClient.close();
				}
			} catch (IOException e) {
				logger.error(e.getMessage());
			}
		}
		return responseContent;
	}

	public byte[] getImageBytesByURL(CloseableHttpClient httpClient1, String httpUrl) {
		CloseableHttpClient httpClient = httpClient1;
		boolean isInnerCreate = false;
		CloseableHttpResponse response = null;
		HttpEntity entity = null;
		byte[] responseBytes = null;
		try {
			// 创建默认的httpClient实例.
			if (httpClient == null) {
				httpClient = HttpClients.createDefault();
				isInnerCreate = true;
			}
			HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求
			httpGet.setConfig(requestConfig);

			// 执行请求
			response = httpClient.execute(httpGet);
			entity = response.getEntity();
			responseBytes = InputStreamUtils.InputStreamTOByte(entity.getContent());
			return responseBytes;
		} catch (Exception e) {
			logger.error(e.getMessage());
		} finally {
			try {
				// 关闭连接,释放资源
				if (response != null) {
					response.close();
				}
				if (isInnerCreate) {
					if (httpClient != null) {
						httpClient.close();
					}
				}
			} catch (IOException e) {
				logger.error(e.getMessage());
			}
		}
		return null;
	}

	/**
	 * 获取本地id地址及tomcat的端口 如:http//192.168.1.113:8080
	 * 
	 * @return
	 * @throws Exception
	 * @author 余伟
	 * @serialData 2018年3月15日
	 */
	public String getLocalIpAddressAndTomcatPort() throws Exception {
		MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
		Set<ObjectName> objs = mbs.queryNames(new ObjectName("*:type=Connector,*"),
				Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
		String host = InetAddress.getLocalHost().getHostAddress();
		String port = objs.iterator().next().getKeyProperty("port");
		String ipadd = "http" + "://" + host + ":" + port;
		return ipadd;
	}

	/**
	 * get 请求
	 * @author zhangyong created on 2020/1/6 4:57 下午
	 * @param url 请求地址
	 * @param headers 请求头
	 * @param querys 请求参数
	 * @return HttpResponse
	 * @throws Exception
	 */
	public static String doGet(String url,
									 Map<String, String> headers,
									 Map<String, String> querys) throws Exception {
		HttpClient httpClient = HttpClients.createDefault();

		HttpGet request = new HttpGet(buildUrl(url, querys));
		for (Map.Entry<String, String> e : headers.entrySet()) {
			request.addHeader(e.getKey(), e.getValue());
		}
		HttpResponse response = httpClient.execute(request);
		return EntityUtils.toString(response.getEntity());
	}
	
    public static String doPost(String url, Map<String, String> headers, Map<String, String> querys) throws Exception {
        HttpClient httpClient = HttpClients.createDefault();
        HttpPost request = new HttpPost(buildUrl(url, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        HttpResponse response = httpClient.execute(request);
        return EntityUtils.toString(response.getEntity());
    }	


	private static String buildUrl(String url, Map<String, String> querys) throws UnsupportedEncodingException {
		StringBuilder sbUrl = new StringBuilder();
		sbUrl.append(url);
		if (null != querys) {
			StringBuilder sbQuery = new StringBuilder();
			for (Map.Entry<String, String> query : querys.entrySet()) {
				if (0 < sbQuery.length()) {
					sbQuery.append("&");
				}

				if (StringUtils.isEmpty(query.getKey()) && !StringUtils.isEmpty(query.getValue())) {
					sbQuery.append(query.getValue());
				}
				if (!StringUtils.isEmpty(query.getKey())) {
					sbQuery.append(query.getKey());
					if (!StringUtils.isEmpty(query.getValue())) {
						sbQuery.append("=");
						sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
					}
				}
			}
			if (0 < sbQuery.length()) {
				sbUrl.append("?").append(sbQuery);
			}
		}

		return sbUrl.toString();
	}
}
